package com.ruoyi.web.controller.common;

import com.alibaba.druid.support.json.JSONUtils;
import com.alibaba.fastjson2.JSONObject;
import com.ruoyi.common.constant.Constants;
import com.ruoyi.common.core.domain.AjaxResult;
import com.ruoyi.framework.web.service.SysLoginService;
import com.ruoyi.web.controller.tool.CheckWxTokenUtils;
import com.ruoyi.web.domain.WechatTokenResponse;
import io.swagger.annotations.ApiOperation;
import io.swagger.v3.oas.annotations.tags.Tag;
import org.apache.commons.lang3.RandomUtils;
import org.apache.logging.log4j.LogManager;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.http.HttpEntity;
import org.springframework.http.HttpHeaders;
import org.springframework.http.MediaType;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.client.RestTemplate;


import javax.servlet.http.HttpServletRequest;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.net.URLEncoder;
import java.nio.charset.StandardCharsets;
import java.time.Duration;
import java.util.*;
import java.util.stream.Collectors;

@RestController
@RequestMapping("/wx")
@Tag(name = "微信回调接口")
//@Slf4j
public class WxCheckController {
    private static final org.apache.logging.log4j.Logger log = LogManager.getLogger(WxCheckController.class);
//    private static final Logger log = LoggerFactory.getLogger(WxCheckController.class);
    private CheckWxTokenUtils checkWxTokenUtils;

    @Value("${wechat.appid}")
    private String APPID;
    @Value("${wechat.appSecret}")
    private String APPSECRET;
//    private static final String APPID = "wx96160d3735054564";
//    private static final String APPSECRET = "d1c18f11a1dc8a91a1145b3969676ba3";
    // 发起请求
    @Autowired
    private RestTemplate restTemplate;
    @Autowired
    private RedisTemplate redisTemplate;
    @Autowired
    private SysLoginService loginService;

    @GetMapping("/callback")
    @ApiOperation("微信回调接口")
    public String callback(HttpServletRequest request) {
        String signature = request.getParameter ("signature");
        String timestamp = request.getParameter ("timestamp");
        String nonce = request.getParameter ("nonce");
        String echostr = request.getParameter ("echostr");

    if(CheckWxTokenUtils.checkSignature(signature, timestamp, nonce)){
        return echostr;
    }
        return "错误";
    }
    // 添加POST方法用于接收微信推送消息
    @PostMapping("/callback")
    @ApiOperation("微信消息推送接口")
    public String callbackPost(HttpServletRequest request) throws Exception {
        // 1. 读 query 参数做签名校验（你已经有了）
        String signature = request.getParameter("signature");
        String timestamp = request.getParameter("timestamp");
        String nonce     = request.getParameter("nonce");
        log.info("微信主动发送参数：{}", request);
        if (!CheckWxTokenUtils.checkSignature(signature, timestamp, nonce)) {
            return "验证失败";
        }

        // 2. 读取 POST body（微信发的 XML）
        String body;
        try (BufferedReader br = new BufferedReader(
                new InputStreamReader(request.getInputStream(), StandardCharsets.UTF_8))) {
            body = br.lines().collect(Collectors.joining(System.lineSeparator()));
        }
        // 解析xml
        Map<String, String> xmlData = parseXml(body);
        log.info("xmlData: {}", xmlData);
//        获取微信推送的参数
        // 获取关键字段
        String toUserName = xmlData.get("ToUserName");     // 开发者微信号
        String fromUserName = xmlData.get("FromUserName"); // 发送方账号（OpenID）
        String createTime = xmlData.get("CreateTime");     // 消息创建时间
        String msgType = xmlData.get("MsgType");           // 消息类型
        String content = xmlData.get("Content");           // 文本消息内容
        String msgId = xmlData.get("MsgId");
        String event = xmlData.get("Event");
        String eventKey = xmlData.get("EventKey");
        log.info("接收到微信消息：",body);


        if("event".equals(msgType)){
            // 用户第一次扫码是关注
            if ("subscribe".equals(xmlData.get("Event"))) {
                // 用户关注事件，异步发送欢迎消息
                sendTml(fromUserName);
            }else{
            //     其他情况就是想登录平台，提供一个登录的链接按钮
                String scene = eventKey;
                String openid = fromUserName;   // 谁扫的

                // 4. 拼返回 XML（文本消息）
                long now = System.currentTimeMillis() / 1000;
                //扫码的时候存储扫码人的openid  只保存1分钟
                redisTemplate.opsForValue()
                        .set("qr:openid:" + scene,openid,Duration.ofMinutes(1));

                return String.format(
                        "<xml>" +
                                "<ToUserName><![CDATA[%s]]></ToUserName>" +
                                "<FromUserName><![CDATA[%s]]></FromUserName>" +
                                "<CreateTime>%d</CreateTime>" +
                                "<MsgType><![CDATA[text]]></MsgType>" +
                                "<Content><![CDATA[点击确认登录 PC 端\n<a href=\"http://192.168.60.27:9090/wx/confirm?scene=%s\">确认登录</a>]]></Content>" +
                                "</xml>",
                        openid, toUserName, now, scene
                );
            }

        }else if("text".equals(msgType)){
//            sendTextTml(fromUserName);
            String scene = eventKey;
            String openid = fromUserName;   // 谁扫的

            // 4. 拼返回 XML（文本消息）
            long now = System.currentTimeMillis() / 1000;
            return String.format(
                    "<xml>" +
                            "<ToUserName><![CDATA[%s]]></ToUserName>" +
                            "<FromUserName><![CDATA[%s]]></FromUserName>" +
                            "<CreateTime>%d</CreateTime>" +
                            "<MsgType><![CDATA[text]]></MsgType>" +
                            "<Content><![CDATA[点击确认登录 PC 端\n<a href=\"https://192.168.60.27:9090/wx/confirm?scene=%s\">确认登录</a>]]></Content>" +
                            "</xml>",
                    openid, toUserName, now, scene
            );
        }
//        sendTml(fromUserName);
        // 4. 先回 success，保证微信不再报错
        return "success";
    }
    @GetMapping("/wxLogin")
    public AjaxResult WXlogin(HttpServletRequest request) throws Exception{
        // 发送请求 调用微信官方接口
        String qrImage = "";
        String frontSceneKey = "";
       try {
           String grant_type = "client_credential";
           String appId = APPID;
           String appScret = APPSECRET;
           String url = "https://api.weixin.qq.com/cgi-bin/token"+"?grant_type="+grant_type+"&appid="+appId+"&secret="+appScret;
//
           ResponseEntity<WechatTokenResponse> response = restTemplate.getForEntity(url, WechatTokenResponse.class);
           WechatTokenResponse tokenResponse = response.getBody();
           log.info("调用微信接口获取access_token: {}", tokenResponse.getAccess_token());
           if(tokenResponse != null){

               String ass_token =  tokenResponse.getAccess_token();
               String url2 = "https://api.weixin.qq.com/cgi-bin/qrcode/create?access_token="+ass_token;
               // 构造请求体参数
               Map<String, Object> qrCodeRequest = new HashMap<>();
               qrCodeRequest.put("expire_seconds", 604800); // 7天过期
               qrCodeRequest.put("action_name", "QR_STR_SCENE");
               Map<String, Object> actionInfo = new HashMap<>();
               Map<String, Object> scene = new HashMap<>();
//               第一次扫码产生随机token和scene值 因为不知道是谁扫的
//               String token = NumberUUID().toString();
               Random random = new Random();
               frontSceneKey =String.valueOf(random.nextInt(100));
               scene.put("scene_str", frontSceneKey);
               actionInfo.put("scene", scene);
               qrCodeRequest.put("action_info",actionInfo);

               ResponseEntity<String> ticketResponse = restTemplate.postForEntity(url2, qrCodeRequest, String.class);
               String ticket = ticketResponse.getBody();
               JSONObject jsonObject = JSONObject.parseObject(ticket);
               if(jsonObject.containsKey("ticket")){
                   String ticketCode = jsonObject.getString("ticket");
                   String tickeyUrl = jsonObject.getString("url");
                   String encodeTicket = URLEncoder.encode(ticketCode, "utf-8");
                   String url3 = "https://mp.weixin.qq.com/cgi-bin/showqrcode?ticket="+encodeTicket;
                   qrImage = url3;
//                   log.info("获取二维码成功: {}", codeImage.getBody());
//                   return codeImage.getBody();
               }
               log.info("调用微信接口获取二维码: {}", ticketResponse.getBody());

           }
       } catch (Exception e) {
           e.printStackTrace();
       }
        HashMap<String, Object> qrcodeObj = new HashMap<>();
        qrcodeObj.put("qrcode", qrImage);
        Random random = new Random();
        String qrtoken = "qazwsx" + random.nextInt(100);
        qrcodeObj.put("token", qrtoken);
        redisTemplate.opsForValue().set("qr:token2scene:"+qrtoken,frontSceneKey,Duration.ofMinutes(5));

        return AjaxResult.success(qrcodeObj);
    }
//    用户关注发送信息
    @PostMapping("/sendTml")
    public String sendTml(String openid) throws Exception {
        String appid = APPID;
        String secret = APPSECRET;

        String tokenUrl = "https://api.weixin.qq.com/cgi-bin/token?"+"grant_type=client_credential&appid="+appid+"&secret="+secret;
        WechatTokenResponse weChatToken = restTemplate.getForObject(tokenUrl, WechatTokenResponse.class);
        String accessToken = weChatToken.getAccess_token();

        Map<String, String> templateMessage = new HashMap<>();
        templateMessage.put("touser", openid);
        templateMessage.put("template_id", "gnZLOkJWrCUFJAi-dUqw-mv_fPV4mXCkgF3pMkAt4yE");
        String body = JSONObject.toJSONString(templateMessage);
        ResponseEntity<String> resp = restTemplate.postForEntity("https://api.weixin.qq.com/cgi-bin/message/template/send?access_token=" + accessToken, body, String.class);
        log.info("模板消息发送结果：{}", resp);
        return  "success";
    }
//    用户发信息自动回复
    public String sendTextTml(String openid) throws Exception {
    String appid = APPID;
    String secret = APPSECRET;

    String tokenUrl = "https://api.weixin.qq.com/cgi-bin/token?"+"grant_type=client_credential&appid="+appid+"&secret="+secret;
    WechatTokenResponse weChatToken = restTemplate.getForObject(tokenUrl, WechatTokenResponse.class);
    String accessToken = weChatToken.getAccess_token();
    log.info("access_token: {}", accessToken);
    Map<String, Object> templateMessage = new HashMap<>();


    templateMessage.put("touser", openid);
    templateMessage.put("template_id", "eplqjYr6bycl8NujsdqfZ0PyNSQSb1_6f08vNS1tFHo");
    templateMessage.put("url", "http://14.103.185.32:82/login");
    Map<String, Object> data = new HashMap<>();
    
    Map<String, String> nameData = new HashMap<>();
    String raw = "马梦磊";
    String clean = raw.replaceAll("\\u200B|\\uFEFF|\\u3000", "").trim();
    nameData.put("value", clean);

    data.put("name", nameData);
    
    Map<String, String> ageData = new HashMap<>();
    ageData.put("value", "158");
    ageData.put("color", "#173177");
    data.put("age", ageData);
    
    templateMessage.put("data", data);
    String body = JSONObject.toJSONString(templateMessage);
    log.info("body:{}", body);
    String url = "https://api.weixin.qq.com/cgi-bin/message/template/send?access_token=" + accessToken;
    HttpHeaders headers = new HttpHeaders();
    headers.setContentType(MediaType.APPLICATION_JSON_UTF8);

// 3. 构造 HttpEntity<String>
    HttpEntity<String> entity = new HttpEntity<>(body, headers);
    ResponseEntity<String> resp = restTemplate.postForEntity(url, entity, String.class);
    log.info("模板消息发送结果：{}", resp);
    return  "success";
}
    // 给用户推送登录链接信息
    public String sendLoginTml(String openid) throws Exception {
        String appid = APPID;
        String secret = APPSECRET;

        String tokenUrl = "https://api.weixin.qq.com/cgi-bin/token?"+"grant_type=client_credential&appid="+appid+"&secret="+secret;
        WechatTokenResponse weChatToken = restTemplate.getForObject(tokenUrl, WechatTokenResponse.class);
        String accessToken = weChatToken.getAccess_token();
        log.info("access_token: {}", accessToken);
        return null;
    }

    // 用户点击确认按钮后，微信服务器会向填写了开发者服务器URL的URL，发送一个GET请求，GET请求携带参数code。
    @GetMapping("/confirm")
    public String confirm(HttpServletRequest request,@RequestParam String scene) throws Exception {
        log.info("点击确认发送参数request: {}", scene);
        // 点击确认存储 scene信息 标记当前用户点击了登录  设置30s 30s未点确认就失效
        redisTemplate.opsForValue().set("qr:status:"+scene,"ok",Duration.ofSeconds(120));
//        String loginRedis = "wx:"+openid;
//        redisTemplate.opsForValue().set(loginRedis, "test", Duration.ofSeconds(30));
        return "登录成功";
    }
    @GetMapping ("/checkLogin")
    public AjaxResult checkLogin(HttpServletRequest request,@RequestParam String token) throws Exception {
//        String openid = request.getParameter("openid");
        try{
            log.info("token:{}",token);
            String secnkey = "qr:token2scene:" + token;
            String scene = (String) redisTemplate.opsForValue().get(secnkey);
            if(scene == null) return AjaxResult.error("请重新扫码");
            String stutus =(String) redisTemplate.opsForValue().get("qr:status:"+scene);
            if("ok".equals(stutus)){
                String openid =(String) redisTemplate.opsForValue().get("qr:openid:"+scene);
                String tokenByOpenId = loginService.loginByOpenId(openid);
                AjaxResult ajax = AjaxResult.success();
                ajax.put(Constants.TOKEN, tokenByOpenId);
                return ajax;
            }
            return AjaxResult.success("响应成功",null);
        }catch (Exception e){
            log.error("微信回调接口异常",e);
            return AjaxResult.error(e.getMessage());
        }
    }
//    一键登录
    @PostMapping("/one-click-login")
    public AjaxResult oneClickLogin(@RequestParam(value = "code", required = true) String Code) throws Exception {
        String appid = "wxddc0f88bcef9f576";
        String secret = "60044fb22c2fdeaa3f0b82f9fa88925d";
//            用code去换openId
        String url = "https://api.weixin.qq.com/sns/jscode2session?appid="+appid+"&secret="+secret+"&js_code="+Code+"&grant_type=authorization_code";
        String restTemplateForObject = restTemplate.getForObject(url, String.class, new Object[]{});
        JSONObject jsonObject = JSONObject.parseObject(restTemplateForObject);
        String openid = jsonObject.getString("openid");
        String wxToken = loginService.loginByOpenId(openid);
        AjaxResult ajax = AjaxResult.success();
        ajax.put(Constants.TOKEN, wxToken);

        return  ajax;
    }
    /**
     * 解析XML字符串为Map
     */
    private Map<String, String> parseXml(String xml) throws Exception {
        Map<String, String> resultMap = new HashMap<>();

        // 使用DOM解析
        javax.xml.parsers.DocumentBuilderFactory factory = javax.xml.parsers.DocumentBuilderFactory.newInstance();
        javax.xml.parsers.DocumentBuilder builder = factory.newDocumentBuilder();
        org.w3c.dom.Document document = builder.parse(new java.io.ByteArrayInputStream(xml.getBytes("UTF-8")));

        // 获取根节点下的所有子节点
        org.w3c.dom.NodeList nodeList = document.getDocumentElement().getChildNodes();

        for (int i = 0; i < nodeList.getLength(); i++) {
            org.w3c.dom.Node node = nodeList.item(i);
            if (node.getNodeType() == org.w3c.dom.Node.ELEMENT_NODE) {
                String nodeName = node.getNodeName();
                String nodeValue = node.getTextContent();
                resultMap.put(nodeName, nodeValue);
            }
        }

        return resultMap;
    }
}
